package org.dslintegration.merge.simple;

import org.dslintegration.mRules.Expression;
import org.dslintegration.mRules.LeftAttribute;
import org.dslintegration.mRules.RightAttribute;
import org.dslintegration.mRules.Rule;
import org.dslintegration.mRules.RuleStatement;
import org.dslintegration.merge.KM3MetamodelUtils;
import org.dslintegration.merge.core.IRule;
import org.dslintegration.merge.core.MergeContext;
import org.dslintegration.merge.core.exception.MergeException;
import org.dslintegration.merge.km3.core.Attribute;
import org.dslintegration.merge.km3.core.Class;
import org.dslintegration.merge.km3.core.Reference;
import org.dslintegration.merge.km3.core.StructuralFeature;

public class SimpleMerge implements IRule {

	@Override
	public void merge(RuleStatement statement, MergeContext context) throws MergeException {
		Rule rule = (Rule) statement.eContainer();
		Expression expression = statement.getExpession();
		if (expression.getLeft() == null || expression.getLeft().size() != 1 || expression.getRight() == null || expression.getRight().size() != 1)
			throw new MergeException();

		Class output = KM3MetamodelUtils.findClass(rule.getOutput().getQualifiedName(), context, false);

		// Process is done in several steps, first we need to find the left and right object and see what type is it (Class or package)
		LeftAttribute leftAttribute = expression.getLeft().get(0);
		RightAttribute rightAttribute = expression.getRight().get(0);

		// FIXME: This should be dynamically assgned based on dominant

		StructuralFeature left = null;
		StructuralFeature right = null;
		// Now we need to alter attributes
		for (StructuralFeature feature : output.getStructuralFeatures()) {
			if (feature.getName().equals(leftAttribute.getAttributeName())) {
				left = feature;
			}
			if (feature.getName().equals(rightAttribute.getAttributeName())) {
				right = feature;
			}
			if (left != null && right != null)
				break;
		}
		// We need to check if types match
		if (!left.getType().getName().equals(right.getType().getName())) {
			throw new MergeException();
		}

		StructuralFeature newFeature = null;
		if (left instanceof Attribute)
			newFeature = new Attribute();
		if (left instanceof Reference) {
			newFeature = new Reference();

			Reference lref = (Reference) left;
			Reference rref = (Reference) right;
			if(lref.getOpposite() !=null)
			((Reference) newFeature).setOpposite(((Reference) left).getOpposite());
			if (lref.getOpposite() != null)
				lref.getOpposite().setOpposite((Reference) newFeature);
			if (rref.getOpposite() != null)
				rref.getOpposite().setOpposite((Reference) newFeature);

		}
		newFeature.setLower(left.getLower());
		newFeature.setUpper(left.getUpper());
		newFeature.setName(statement.getOutputAttribute());
		newFeature.setType(left.getType());
		// ADd new attribute
		newFeature.setParent(output);
		context.add(newFeature);
		// Remove old
		context.remove(left);
		context.remove(right);

	}

	protected void mergePackages() {

	}

}
